/**
 * @author Ruben Weiejrs
 * @author Geert de Leeuw
 * @since 19-02-'08
 */
var module = "";
var DynForm = new Class({
	list: null,
	loader: null,
	type: null,				//type of list: students, classes or modules
	engine: null,			//reference to engine obj
	rows: null,				//number of rows in current list
	self: null,
	maxSize: 18,
	title: null,
	selectedRow: null,
	
	
	initialize: function (name, engine, self) {
		if ($(name+"Holder"))
			this.list = $(name+"Holder");
		if (!$defined(self))
			self = this;
		
		this.self	= self;
		this.loader	= new Loader(name);
		this.type	= name;
		this.engine = engine;
		this.title	= $('title'+name);
		
		//add event listeners
		this.addEvent('update', Delegate(this.self, this.load));
		this.engine.addEvent('update', Delegate(this.self, this.load));
		this.loader.addEvent('loaded', Delegate(this.self, this.fillList));
		this.loader.addEvent('failed', Delegate(this.self, this.onLoadFailed));
		this.load();
	},
	
	
	clearList: function () {
		this.list.empty();
	},
	
	
	load: function (params) {
		this.title.addClass('loading');
		this.loader.load(params);
	},
	
	
	clear: function () {},
	onLoadFailed: function () {
		this.title.removeClass('loading');
	},
	
	
	fillList: function (data) {
		this.title.removeClass('loading');
		this.clearList();
		this.rows = 0;
		
		/*if (data.length == 0) {
			this.clear();
			return;
		}*/
		
		data.each(Delegate(this,this.addRow));
		var rows = this.rows;
		if (rows < 2)				rows = 2;
		if (rows > this.maxSize)	rows = this.maxSize; 
		this.list.setProperty('size', rows);
	},
	
	
	addRow: function (rowData) {
		var labelTxt= rowData.label == null ? rowData.id : rowData.label;
		var p		= new Element ("p");
	 	var label	= new Element ("label", {'for': "class_"+rowData.id});
	 	var input	= new Element ("input", {id: "class_"+rowData.id, type: "checkbox", name:this.type+"[]", value: rowData.id});
	 	input.addEvent('change', Delegate(this, this.onSelection));
		
		//change color of odd rows
		if (this.rows % 2 == 0)
			p.addClass('odd');
			
		label.setHTML(labelTxt);
		
		label.injectInside(p);
		input.injectInside(p);
		p.injectInside(this.list);
		this.rows++;
	},
	
	
	onSelection: function (e) {
		if (e.target.checked)	e.target.getParent().addClass('checked');
		else					e.target.getParent().removeClass('checked');
	}
});
DynForm.implement(new Events);


var DataField = DynForm.extend({
	input: null,			//input textfield
	btn: null,				//clear button
	
	inputTimer: null,		//interval-id van timer van zoekveld
	value: "",				//current value
	selected: false,		//is there an item selected in the current list
	
	
	initialize: function (type, engine) {
		this.list	= $('data'+type);
		this.input	= $('search'+type);
		this.btn	= $('clear'+type);
		
		this.list.addEvent('dblclick', Delegate(this, this.clear));
		this.list.addEvent('change', Delegate(this, this.onSelection));
		this.input.addEvent('keyup', Delegate(this, this.onTextInput));
		this.btn.addEvent('click', Delegate(this, this.clear));
		
		this.parent(type, engine);
		this.clear();
	},

	
	load: function (params) {
		if (this.selected)	return;
		this.title.addClass('loading');
		this.loader.load(params);
	},
	
	
	addRow: function (rowData) {
		var row		= new Element ("option", {value: rowData.id});
		var label	= rowData.label == null ? rowData.id : rowData.label + " ("+rowData.id+")";
		
		//change color of odd rows
		if (this.rows % 2 == 0)
			row.addClass('odd');
		
		//kijk of er een highlight mee wordt gegeven
		if ($defined(rowData.highlight)) {
			if (rowData.highlight == -1)	row.addClass('downlight');
			else							row.addClass('highlight');
		}
		
		if (rowData.id == this.value) {
			this.list.selectedIndex = row;
		}
		
		row.data = rowData;
		row.setHTML(label);
		row.injectInside(this.list);
		this.rows++;
	},
	
	
	clear: function (keepInput) {
		this.selected = false;
		if (keepInput != true) { this.setValue(""); }
		this.list.selectedIndex = -1;
		this.fireEvent("cleared");
	},
	
	
	setValue: function (value) {
		if (value == "")	this.btn.addClass("hide");
		else				this.btn.removeClass("hide");
		this.value = this.input.value = value;
	},


	onSelection: function (e) {
		this.selectedRow	= this.list.options[this.list.selectedIndex];
		this.selected		= true;
		this.setValue(this.list.value);
		this.fireEvent("newSelection");
	},
	
	
	onTextInput: function () {
		if (this.selected) {
			//if there was anything selected, the other list should change when the user starts typing in this inputfield
			this.clear(true);
		}
		if (this.input.value == "") {
			//when all inputdata is deleted, we should reset all fields and stop searching 
			this.clear();
			return;
		}
		if (this.inputTimet != null) {
			this.inputTimer = $clear(this.inputTimer);
		}
		var params = {};
		params[this.type] = this.input.value;
		this.inputTimer = this.fireEvent("update",[params],300);
	}
});


var DataTable = DynForm.extend({
	fieldname: null,
	module: null,


	initialize: function (type, fieldname, engine) {
		this.list		= $('data'+type);
		this.fieldname	= fieldname;
		this.parent(type, engine);
	},
	
	
	load: function (params) {
		this.title.addClass('loading');
		this.loader.load({modules: module});
	},
	
	
	addRow: function (rowData) {
		var row		= $('example'+this.type).clone();
		row.removeClass('hide');
		row.id		= this.type+"row"+this.rows;
		
		row.getElementsByTagName('td')[0].setHTML(rowData.label);
		
		var inputFields		= row.getElementsByTagName('input');
		inputFields[2] 		= row.getElementsByTagName('textarea')[0];
		
		//set names
		var name = this.fieldname + "[" + this.rows + "]";
		for (var i = 0; i < 3; i++) {
			if (!inputFields[i])		continue;
			inputFields[i].setProperty('name', name + inputFields[i].name);
		}
		
		inputFields[0].value = rowData.id;
		
		//change color of odd rows
		if (this.rows % 2 == 0)
			row.addClass('odd');
		
		//kijk of er een highlight mee wordt gegeven
		if ($defined(rowData.highlight)) {
			if (rowData.highlight == -1)	row.addClass('downlight');
			else							row.addClass('highlight');
		}
		
		if (rowData.id == this.value) {
			this.list.selectedIndex = row;
		}
		
		row.data = rowData;
		//row.setHTML(label);
		row.injectInside(this.list);
		this.rows++;
	}
});


var Rating = new Class({
	student: null,
	module: null,
	criteria: null,
	competenties: null,
	
	
	initialize: function (engine) {
		var tmp = window.location.hash.substr(1).split('&');
		this.student = tmp[0];
		module = this.module = tmp[1];
		
		this.criteria = new DataTable('criteria', 'part_of_rating', engine, this.module);
		this.compenties = new DataTable('competenties', 'competentions', engine, this.module);
		
		//fill in inputfield
		$('stuNr').value = this.student;
		$('module').value = this.module;
	}
});


var Message = new Class({
	target: null,
	
	initialize: function (message) {
		this.target = new Element('p', {'class': 'message'});
		this.target.setHTML(message);
		this.target.injectInside($('results'));
		this.addEvent('hide', this.hide);
		this.fireEvent('hide', [], 6000);
	},
	
	hide: function (e) {
		this.target.remove();
	}
});
Message.implement(new Events);


var Engine = new Class({
	fieldNames: {'students':null, 'modules':null , 'classes':null, 'criteria':null, 'competenties':null},
	fields: {},
	form: null,
	loader: null,
	
	start: function () {
		this.addEvent('refresh', this.refresh);
		this.addEvent('loaded', Delegate(this, this.onEmailed));
		
		this.loader = new Loader('email');
		this.loader.addEvent('loaded', Delegate(this, this.onEmailed));
		this.loader.addEvent('failed', Delegate(this, this.onEmailedFailed));
		
		if ($("newInput")) {
			for (var i in this.fieldNames) {
				if (!$(i+"Holder"))		continue;
				this.fields[i] = new DynForm(i, this);
			}
			
			this.form = $("newInput");
		}
		
		else if ($("ratingForm")) {
			new Rating(this);
			this.form = $("ratingForm");
		}
		
		else {
			for (var i in this.fieldNames) {
				if (!$("data"+i))		continue;
				this.fields[i] = new DataField(i, this);
				this.fields[i].addEvent('newSelection', Delegate(this, this.onSelection));
				this.fields[i].addEvent('newSelection', Delegate(this, this.manageButtons));
				this.fields[i].addEvent('cleared', Delegate(this, this.onSelection));
			}
			
			//menu buttons popup laten openen
			var links = $$('.menulink').addEvent('click', this.openWindow);
		}
		
		if ($("closeBtn")) {
			$("closeBtn").addEvent('click', this.closeWindow);
		}
		
		if ($defined(this.form)) {
			this.form.addEvent('submit', Delegate(this, this.onSubmit));
		}
	},
	
	
	refresh: function () {
		this.fields.classes.clear();
		this.fields.students.clear();
		//this.onSelection();
	},
	
	
	onSelection: function () {
		var params = {};
		for (var i in this.fields) {
			if (this.fields[i].value == "")		continue;
			params[i] = this.fields[i].value;
		}
		this.fireEvent("update", params);
	},
	
	
	onSubmit: function (e) {
		new Event(e).stop();
		if ($defined(this.form.sended) && this.form.sended)		return; 
		
		this.form.sended = true;
		this.form.send({onComplete: Delegate(this, this.onSended)});
	},
	
	
	onEmailed: function (response) {
		new Message("Er zijn "+response.mails+" emails verstuurd.");
	},
	
	
	onEmailedFailed: function (response) {
		new Message("Het emailen is gelukt.");
	},
	
	
	onSended: function (response) {
		var obj = Json.evaluate(response);
		var success = true;
		for (var i in obj) {
			if (obj[i] == 0) {
				sucess = false;
				break;
			}
		}
		
		if (success) {
			//display message
			window.opener.fireEvent("newMessage", ["Het toevoegen is gelukt."]);
			
			//close window
			this.closeWindow();
		} else {
			var message = new Message("Het toevoegen is niet gelukt");
		}
	},
	
	
	manageButtons: function () {
		if (this.fields.students.selected && this.fields.modules.selected) {
			//only show button if student is n't judged already
			if (this.fields.students.selectedRow.data.highlight > -1) {
				$("judgeBtn").addClass("hide");
				return;
			}
			
			$("judgeBtn").setHTML("Beoordeel student " + this.fields.students.value);
			$("judgeBtn").url = 'newRating.html#' + this.fields.students.value + "&" + this.fields.modules.value;
			$("judgeBtn").onclick = this.openWindow;
			$("judgeBtn").removeClass("hide");
		} else {
			$("judgeBtn").addClass("hide");
		}
		
		if (this.fields.classes.selected && this.fields.modules.selected) {
			$("emailBtn").setHTML("Email klas "+this.fields.classes.value);
			//$("emailBtn").url = 'main.php?action=email&classes=' + this.fields.classes.value + "&modules=" + this.fields.modules.value;
			$("emailBtn").onclick = Delegate(this, this.sendMails);
			$("emailBtn").removeClass("hide");
		} else {
			$("emailBtn").addClass("hide");
		}
	},
	
	
	sendMails: function (e) {
		this.loader.load({classes: this.fields.classes.value, modules: this.fields.modules.value});
	},
	
	
	openWindow: function (e) {
		var url = $defined(this.url) ? this.url : this.id + ".html";
		window.open(url, "popup", "width=1000,height=600,resizable=yes,scrollbars=yes");
	},
	
	
	closeWindow: function (e) {
		window.opener.refresh();
		window.close();
	}
});
Engine.implement(new Events);


var Loader = new Class({
	baseUrl: 'main.php',
	checksum: null,
	
	
	initialize: function (action) {
		this.baseUrl += '?action='+action;
	},
	
	
	load: function (args) {
		var url = this.baseUrl;
		if ($defined(args)) {
			for (var i in args)		url += "&" + i + "=" + args[i];
		}
		
		var request = new Json.Remote(url, {
			onComplete: Delegate(this, this.onFieldData),
			onFailure: Delegate(this, this.onFailure),
		}).send();
	},
	
	
	onFailure: function (e) {
		this.fireEvent("failed");
	},
	
	
	onFieldData: function (data) {
		if (data.checksum == this.checksum || $type(data.data) != "array") {
			this.fireEvent("failed");
			return;
		}
		
		this.checksum = data.checksum;
		this.fireEvent("loaded", [data.data]);
	}
});
Loader.implement(new Events);


var engine = new Engine();
window.addEvent('domready', Delegate(engine, engine.start));
window.addEvent('newMessage', function (m) { new Message(m); });

if (window.focus) {
	window.addEvent('domready', window.focus);
}

function refresh () {
	engine.fireEvent("refresh", null, 100);
}


function Delegate ( that, thatMethod ) {
	if (arguments.length > 2) {
		var _params = [];
		for(var n = 2; n < arguments.length; ++n) _params.push(arguments[n]);
		return function() {
			if (arguments.length > 0)	for(var i = 0; i < arguments.length; i++) _params.push(arguments[i]);
			return thatMethod.apply(that,_params);
		}
	} else {
		return function () { return thatMethod.apply(that,arguments); }
	}
}